#include "cx_sddl.h"
#include <sddl.h> // ConvertSidToStringSidA
#include <array>
#include <format>

#include <numeric>       // std::accumulate
#include <AclAPI.h>      // For ACL and SDDL functions
#include <algorithm>     // For std::transform
#include <sddl.h>        // For ConvertSecurityDescriptorToStringSecurityDescriptorW
#include <hidsdi.h>      // For HidD_GetAttributes
#include <SetupAPI.h>     // For SetupDi functions

#include "cx_string/cx_string.h"

#pragma comment(lib, "setupapi.lib")
#pragma comment(lib, "hid.lib")

namespace CXLib {

	namespace CXSddl {
		const std::unordered_map<std::string, std::string> sidDesc = {
		{"AA", "ACCESS_CONTROL_ASSISTANCE_OPS"},
		{"AC", "ALL_APP_PACKAGES"},
		{"AN", "ANONYMOUS"},
		{"AO", "ACCOUNT_OPERATORS"},
		{"AP", "PROTECTED_USERS"},
		{"AU", "AUTHENTICATED_USERS"},
		{"BA", "BUILTIN_ADMINISTRATORS"},
		{"BG", "BUILTIN_GUESTS"},
		{"BO", "BACKUP_OPERATORS"},
		{"BU", "BUILTIN_USERS"},
		{"CA", "CERT_SERV_ADMINISTRATORS"},
		{"CD", "CERTSVC_DCOM_ACCESS"},
		{"CG", "CREATOR_GROUP"},
		{"CN", "CLONEABLE_CONTROLLERS"},
		{"CO", "CREATOR_OWNER"},
		{"CY", "CRYPTO_OPERATORS"},
		{"DA", "DOMAIN_ADMINISTRATORS"},
		{"DC", "DOMAIN_COMPUTERS"},
		{"DD", "DOMAIN_DOMAIN_CONTROLLERS"},
		{"DG", "DOMAIN_GUESTS"},
		{"DU", "DOMAIN_USERS"},
		{"EA", "ENTERPRISE_ADMINS"},
		{"ED", "ENTERPRISE_DOMAIN_CONTROLLERS"},
		{"EK", "ENTERPRISE_KEY_ADMINS"},
		{"ER", "EVENT_LOG_READERS"},
		{"ES", "RDS_ENDPOINT_SERVERS"},
		{"HA", "HYPER_V_ADMINS"},
		{"HI", "ML_HIGH"},
		{"HO", "USER_MODE_HARDWARE_OPERATORS"},
		{"IS", "IIS_USERS"},
		{"IU", "INTERACTIVE"},
		{"KA", "KEY_ADMINS"},
		{"LA", "LOCAL_ADMIN"},
		{"LG", "LOCAL_GUEST"},
		{"LS", "LOCAL_SERVICE"},
		{"LU", "PERFLOG_USERS"},
		{"LW", "ML_LOW"},
		{"ME", "ML_MEDIUM"},
		{"MP", "ML_MEDIUM_PLUS"},
		{"MU", "PERFMON_USERS"},
		{"NO", "NETWORK_CONFIGURATION_OPS"},
		{"NS", "NETWORK_SERVICE"},
		{"NU", "NETWORK"},
		{"OW", "OWNER_RIGHTS"},
		{"PA", "GROUP_POLICY_ADMINS"},
		{"PO", "PRINTER_OPERATORS"},
		{"PS", "PERSONAL_SELF"},
		{"PU", "POWER_USERS"},
		{"RA", "RDS_REMOTE_ACCESS_SERVERS"},
		{"RC", "RESTRICTED_CODE"},
		{"RD", "REMOTE_DESKTOP"},
		{"RE", "REPLICATOR"},
		{"RM", "RMS__SERVICE_OPERATORS"},
		{"RO", "ENTERPRISE_RO_DCs"},
		{"RS", "RAS_SERVERS"},
		{"RU", "ALIAS_PREW2KCOMPACC"},
		{"SA", "SCHEMA_ADMINISTRATORS"},
		{"SH", "OPENSSH_USERS"},
		{"SI", "ML_SYSTEM"},
		{"SO", "SERVER_OPERATORS"},
		{"SS", "SERVICE_ASSERTED"},
		{"SU", "SERVICE"},
		{"SY", "LOCAL_SYSTEM"},
		{"UD", "USER_MODE_DRIVERS"},
		{"WD", "EVERYONE"},
		{"WR", "WRITE_RESTRICTED_CODE"}
		};

		const std::unordered_map<std::string, std::string> typeDesc = {
			{"A",   "ACCESS_ALLOWED"},
			{"D",   "ACCESS_DENIED"},
			{"OA",	"OBJECT_ACCESS_ALLOWED"},
			{"OD",	"OBJECT_ACCESS_DENIED"},
			{"AU",	"AUDIT"},
			{"AL",	"ALARM"},
			{"OU",	"OBJECT_AUDIT"},
			{"OL",	"OBJECT_ALARM"},
			{"ML",	"MANDATORY_LABEL"},
			{"XA",	"CALLBACK_ACCESS_ALLOWED"},
			{"XD",	"CALLBACK_ACCESS_DENIED"},
			{"RA",	"RESOURCE_ATTRIBUTE"},
			{"SP",	"SCOPED_POLICY_ID"},
			{"XU",	"CALLBACK_AUDIT"},
			{"ZA",	"CALLBACK_OBJECT_ACCESS_ALLOWED"},
			{"TL",	"PROCESS_TRUST_LABEL"},
			{"FL",	"ACCESS_FILTER"}
		};


		const std::vector<RightItem> rightDesc = {
			{"GA",  "SDDL_GENERIC_ALL",	      GENERIC_ALL},
			{"GR",  "SDDL_GENERIC_READ",	  GENERIC_READ},
			{"GW",  "SDDL_GENERIC_WRITE",	  GENERIC_WRITE},
			{"GX",  "SDDL_GENERIC_EXECUTE",	  GENERIC_EXECUTE},
			{"RC",  "SDDL_READ_CONTROL",	  READ_CONTROL},
			{"SD",  "SDDL_STANDARD_DELETE",	  DELETE},
			{"WD",  "SDDL_WRITE_DAC",	      WRITE_DAC},
			{"WO",  "SDDL_WRITE_OWNER",	      WRITE_OWNER},
			{"FA",  "SDDL_FILE_ALL",	      FILE_ALL_ACCESS},
			{"FR",  "SDDL_FILE_READ",         FILE_GENERIC_READ},
			{"FW",  "SDDL_FILE_WRITE",	      FILE_GENERIC_WRITE},
			{"FX",  "SDDL_FILE_EXECUTE",	  FILE_GENERIC_EXECUTE},
			{"KA",  "SDDL_KEY_ALL",	          KEY_ALL_ACCESS},
			{"KR",  "SDDL_KEY_READ",	      KEY_READ},
			{"KW",  "SDDL_KEY_WRITE",	      KEY_WRITE},
			{"KX",  "SDDL_KEY_EXECUTE",	      KEY_EXECUTE}
		};

		std::string cxDescribeSid(const std::string& sid) {
			auto it = sidDesc.find(sid);
			return it != sidDesc.end() ? it->second : "";
		}

		std::string cxDescribeType(const std::string& type) {
			auto it = typeDesc.find(type);
			return it != typeDesc.end() ? it->second : "";
		}

		// Describe rights from string, e.g. "FA" or "0x1201bf"
		std::string cxDescribeRights(const std::string& rights)
		{
			for (const auto& item : rightDesc) {
				if (item.abbr == rights)
					return item.right;
			}

			if (rights.size() > 2 && rights[0] == '0' && (rights[1] == 'x' || rights[1] == 'X')) {
				DWORD value = std::stoul(rights, nullptr, 16);
				std::vector<std::string> descs;
				for (const auto& item : rightDesc) {
					if ((value & item.value) == item.value)
						descs.push_back(item.right);
				}
				if (!descs.empty())
					return std::accumulate(descs.begin() + 1, descs.end(), descs[0],
						[](const std::string& a, const std::string& b) { return a + " | " + b; });
			}

			return "";
		}

		/// <summary>
		/// To parse the ACE string
		/// </summary>
		/// <param name="ace">e.g. "A;;FA;;;SY"</param>
		/// <returns>AceInfo</returns>
		AceInfo cxParseACE(const std::string& ace)
		{
			AceInfo info;
			std::vector<std::string> parts;
			size_t start = 0;
			size_t end = 0;
			while ((end = ace.find(';', start)) != std::string::npos) {
				parts.push_back(ace.substr(start, end - start));
				start = end + 1;
			}
			parts.push_back(ace.substr(start));
			while (parts.size() < 6) parts.emplace_back("");
			info.type = parts[0];
			info.flags = parts[1];
			info.rights = parts[2];
			info.object_guid = parts[3];
			info.inherit_object_guid = parts[4];
			info.account_sid = parts[5];

			info.desc.account_sid_desc = cxDescribeSid(info.account_sid);
			info.desc.type_desc = cxDescribeType(info.type);
			info.desc.rights_desc = cxDescribeRights(info.rights);

			return info;
		}

		/// <summary>
		/// Parse SDDL
		/// </summary>
		/// <param name="sddl">e.g. "D:P(A;;FA;;;SY)(A;;FA;;;BA)(A;;0x1201bf;;;WD)(A;;0x1200a9;;;RC)"</param>
		/// <returns></returns>
		RZSDDLInfo cxParseSDDL(const std::string& sddl)
		{
			std::vector<AceInfo> result;
			size_t pos = 0;
			while ((pos = sddl.find('(', pos)) != std::string::npos) {
				size_t end = sddl.find(')', pos);
				if (end == std::string::npos) break;
				std::string aceStr = sddl.substr(pos + 1, end - pos - 1);
				result.push_back(cxParseACE(aceStr));
				pos = end + 1;
			}


			RZSDDLInfo rz;
			rz.sddl = sddl;
			rz.aces = result;
			rz.isAdmin = std::ranges::any_of(result.begin(), result.end(), [](const AceInfo& ace) {
				if (ace.account_sid != "BA") return false;
				if (ace.rights == "FA" || ace.rights == "GA") return true;
				if (ace.rights.size() > 2 && ace.rights[0] == '0' && (ace.rights[1] == 'x' || ace.rights[1] == 'X')) {
					DWORD value = std::stoul(ace.rights, nullptr, 16);
					return (((value & FILE_GENERIC_READ) == FILE_GENERIC_READ) && ((value & FILE_GENERIC_WRITE) == FILE_GENERIC_WRITE)) ||
						(((value & GENERIC_READ) == GENERIC_READ) && ((value & GENERIC_WRITE) == GENERIC_WRITE));
				}
				return false;
				});
			rz.isEveryone = std::ranges::any_of(result.begin(), result.end(), [](const AceInfo& ace) {
				return ace.account_sid == "WD";
				});

			return rz;
		}

		/// <summary>
		/// 开启或关闭进程的 SE_SECURITY_NAME 特权。开启后，进程可以读取和修改资源的 SACL（系统访问控制列表），用于审计设置。
		/// </summary>
		/// <param name="hProcess">进程句柄</param>
		/// <param name="enable">是否启用特权</param>
		/// <returns>Win32 错误码，0 表示成功</returns>
		DWORD cxEnableSecurityPrivilege(HANDLE hProcess, bool enable)
		{
			HANDLE hToken;
			TOKEN_PRIVILEGES tp;
			LUID luid;
			if (!OpenProcessToken(hProcess, TOKEN_ADJUST_PRIVILEGES, &hToken))
				return ::GetLastError();
			if (!LookupPrivilegeValue(NULL, SE_SECURITY_NAME, &luid))
			{
				CloseHandle(hToken);
				return ::GetLastError();
			}
			tp.PrivilegeCount = 1;
			tp.Privileges[0].Luid = luid;
			tp.Privileges[0].Attributes = enable ? SE_PRIVILEGE_ENABLED : 0;
			if (!AdjustTokenPrivileges(hToken, FALSE, &tp, sizeof(tp), NULL, NULL))
			{
				CloseHandle(hToken);
				return ::GetLastError();
			}
			DWORD err = ::GetLastError();
			CloseHandle(hToken);
			return err;
		}

		/// <summary>
		/// 设置指定设备路径的 SACL（系统访问控制列表）。
		/// 若 enableSACL 为 true，则为 Everyone 添加审计 ACE。
		/// 若 enableSACL 为 false，则移除 SACL（即不设置任何审计规则）。
		/// 需管理员权限，并临时启用 SE_SECURITY_NAME 特权。
		/// </summary>
		/// <param name="devicePath">设备对象路径，如 "\\?\hid#..."</param>
		/// <param name="enableSACL">是否启用 Everyone 的审计 ACE</param>
		/// <returns>Win32 错误码，ERROR_SUCCESS 表示成功</returns>
		DWORD cxSetSACL(const char* path, bool enableSACL)
		{
			auto hProcess = ::GetCurrentProcess();
			if (auto enableRes = cxEnableSecurityPrivilege(hProcess, true); ERROR_SUCCESS != enableRes) {
				return enableRes;
			}

			PACL pSacl = nullptr;
			DWORD res = ERROR_SUCCESS;

			if (enableSACL) {
				// 创建两个 ACE：一个审计成功，一个审计失败
				EXPLICIT_ACCESS ea[2] = {};
				
				// 第一个 ACE：审计成功的文件访问
				ea[0].grfAccessPermissions = FILE_GENERIC_WRITE | DELETE | WRITE_DAC | WRITE_OWNER;
				ea[0].grfAccessMode = SET_AUDIT_SUCCESS;
				ea[0].grfInheritance = NO_INHERITANCE;
				ea[0].Trustee.TrusteeForm = TRUSTEE_IS_NAME;
				ea[0].Trustee.TrusteeType = TRUSTEE_IS_WELL_KNOWN_GROUP;
				ea[0].Trustee.ptstrName = (LPWSTR)L"Everyone";
				
				// 第二个 ACE：审计失败的文件访问
				ea[1].grfAccessPermissions = FILE_GENERIC_WRITE | DELETE | WRITE_DAC | WRITE_OWNER;
				ea[1].grfAccessMode = SET_AUDIT_FAILURE;
				ea[1].grfInheritance = NO_INHERITANCE;
				ea[1].Trustee.TrusteeForm = TRUSTEE_IS_NAME;
				ea[1].Trustee.TrusteeType = TRUSTEE_IS_WELL_KNOWN_GROUP;
				ea[1].Trustee.ptstrName = (LPWSTR)L"Everyone";
				
				SetEntriesInAcl(2, ea, NULL, &pSacl);
			}

			res = SetNamedSecurityInfoA(
				const_cast<char*>(path),
				SE_FILE_OBJECT,
				SACL_SECURITY_INFORMATION,
				NULL, NULL, NULL, pSacl
			);

			if (pSacl) LocalFree(pSacl);

			cxEnableSecurityPrivilege(hProcess, false);

			return res;
		}

		/// <summary>
		/// 使用 SDDL 字符串设置文件 SACL，更直接和可靠的方法
		/// </summary>
		/// <param name="path">文件路径</param>
		/// <param name="enableSACL">是否启用审计</param>
		/// <returns>Win32 错误码</returns>
		DWORD cxSetSACLWithSDDL(const char* path, bool enableSACL)
		{
			auto hProcess = ::GetCurrentProcess();
			if (auto enableRes = cxEnableSecurityPrivilege(hProcess, true); ERROR_SUCCESS != enableRes) {
				return enableRes;
			}

			DWORD res = ERROR_SUCCESS;
			PSECURITY_DESCRIPTOR pSD = nullptr;

			if (enableSACL) {
				// 设置 SACL：审计 Everyone 的文件写入操作（成功和失败）
				LPCWSTR sddl = L"S:(AU;SA;0x40116;;;WD)(AU;FA;0x40116;;;WD)";
				
				if (ConvertStringSecurityDescriptorToSecurityDescriptorW(
					sddl, SDDL_REVISION_1, &pSD, nullptr)) {
					
					PACL pSacl = nullptr;
					BOOL bSaclPresent = FALSE, bSaclDefaulted = FALSE;
					
					if (GetSecurityDescriptorSacl(pSD, &bSaclPresent, &pSacl, &bSaclDefaulted)) {
						res = SetNamedSecurityInfoA(
							const_cast<char*>(path),
							SE_FILE_OBJECT,
							SACL_SECURITY_INFORMATION,
							NULL, NULL, NULL, pSacl
						);
					} else {
						res = GetLastError();
					}
					LocalFree(pSD);
				} else {
					res = GetLastError();
				}
			} else {
				// 移除 SACL
				res = SetNamedSecurityInfoA(
					const_cast<char*>(path),
					SE_FILE_OBJECT,
					SACL_SECURITY_INFORMATION,
					NULL, NULL, NULL, nullptr
				);
			}

			cxEnableSecurityPrivilege(hProcess, false);
			return res;
		}

		/// <summary>
		/// 专门用于设备对象（如 HID 设备）的 SACL 设置函数
		/// 使用 SE_KERNEL_OBJECT 类型和 SetSecurityInfo API
		/// </summary>
		/// <param name="devicePath">设备路径，如 HID 设备路径</param>
		/// <param name="enableSACL">是否启用审计</param>
		/// <returns>Win32 错误码</returns>
		DWORD cxSetDeviceSACL(const char* devicePath, bool enableSACL)
		{
			auto hProcess = ::GetCurrentProcess();
			if (auto enableRes = cxEnableSecurityPrivilege(hProcess, true); ERROR_SUCCESS != enableRes) {
				return enableRes;
			}

			DWORD res = ERROR_SUCCESS;
			HANDLE hDevice = INVALID_HANDLE_VALUE;

			// 打开设备以获取句柄
			hDevice = CreateFileA(devicePath,
				READ_CONTROL | ACCESS_SYSTEM_SECURITY,
				FILE_SHARE_READ | FILE_SHARE_WRITE,
				NULL,
				OPEN_EXISTING,
				0,
				NULL);

			if (hDevice == INVALID_HANDLE_VALUE) {
				res = GetLastError();
				cxEnableSecurityPrivilege(hProcess, false);
				return res;
			}

			PACL pSacl = nullptr;

			if (enableSACL) {
				// 创建审计 ACE：审计权限修改操作
				EXPLICIT_ACCESS ea[2] = {};
				
				// 审计成功的权限修改
				ea[0].grfAccessPermissions = WRITE_DAC | WRITE_OWNER | DELETE;
				ea[0].grfAccessMode = SET_AUDIT_SUCCESS;
				ea[0].grfInheritance = NO_INHERITANCE;
				ea[0].Trustee.TrusteeForm = TRUSTEE_IS_NAME;
				ea[0].Trustee.TrusteeType = TRUSTEE_IS_WELL_KNOWN_GROUP;
				ea[0].Trustee.ptstrName = (LPWSTR)L"Everyone";
				
				// 审计失败的权限修改
				ea[1].grfAccessPermissions = WRITE_DAC | WRITE_OWNER | DELETE;
				ea[1].grfAccessMode = SET_AUDIT_FAILURE;
				ea[1].grfInheritance = NO_INHERITANCE;
				ea[1].Trustee.TrusteeForm = TRUSTEE_IS_NAME;
				ea[1].Trustee.TrusteeType = TRUSTEE_IS_WELL_KNOWN_GROUP;
				ea[1].Trustee.ptstrName = (LPWSTR)L"Everyone";
				
				SetEntriesInAcl(2, ea, NULL, &pSacl);
			}

			// 使用 SetSecurityInfo 设置设备对象的 SACL
			res = SetSecurityInfo(
				hDevice,
				SE_KERNEL_OBJECT,
				SACL_SECURITY_INFORMATION,
				NULL, NULL, NULL, pSacl
			);

			if (pSacl) LocalFree(pSacl);
			CloseHandle(hDevice);
			cxEnableSecurityPrivilege(hProcess, false);

			return res;
		}

		/// <summary>
		/// Get SDDL of HID path
		/// </summary>
		/// <param name="PID"></param>
		/// <param name="VID"></param>
		/// <param name="security">Should be DACL_SECURITY_INFORMATION or SACL_SECURITY_INFORMATION</param>
		/// <returns>
		///     key: HID path   
		///     value: SDDL 
		/// </returns>
		std::unordered_map<std::string, std::string> cxGetHIDsACL(USHORT PID/* = 0*/, USHORT VID /*= 0*/, DWORD security/* = DACL_SECURITY_INFORMATION*/)
		{
			std::unordered_map<std::string, std::string> mapSDDLs;

			GUID hidGUID;
			HidD_GetHidGuid(&hidGUID);

			HDEVINFO hDevInfo = SetupDiGetClassDevs(&hidGUID, NULL, NULL, DIGCF_PRESENT | DIGCF_DEVICEINTERFACE);
			if (hDevInfo == INVALID_HANDLE_VALUE) return mapSDDLs;

			SP_DEVICE_INTERFACE_DATA devInterfaceData = { sizeof(SP_DEVICE_INTERFACE_DATA) };
			DWORD index = 0;

			while (SetupDiEnumDeviceInterfaces(hDevInfo, NULL, &hidGUID, index++, &devInterfaceData))
			{
				DWORD requiredSize = 0;
				SetupDiGetDeviceInterfaceDetail(hDevInfo, &devInterfaceData, NULL, 0, &requiredSize, NULL);

				auto pDetail = (PSP_DEVICE_INTERFACE_DETAIL_DATA)malloc(requiredSize);
				if (!pDetail) continue;
				pDetail->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA);

				SP_DEVINFO_DATA devInfoData = { sizeof(SP_DEVINFO_DATA) };

				if (SetupDiGetDeviceInterfaceDetail(hDevInfo, &devInterfaceData, pDetail, requiredSize, NULL, &devInfoData))
				{
					HANDLE hDevice = CreateFile(pDetail->DevicePath, READ_CONTROL,
						FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL);

					if (hDevice != INVALID_HANDLE_VALUE)
					{
						HIDD_ATTRIBUTES attrib = { sizeof(HIDD_ATTRIBUTES) };
						if (HidD_GetAttributes(hDevice, &attrib) &&
							(VID == 0 || attrib.VendorID == VID) && (PID == 0 || attrib.ProductID == PID))
						{
							PSECURITY_DESCRIPTOR pSD = nullptr;
							DWORD size = 0;
							GetKernelObjectSecurity(hDevice, security, NULL, 0, &size);

							auto dwError = GetLastError();
							if (dwError == ERROR_INSUFFICIENT_BUFFER)
							{
								pSD = (PSECURITY_DESCRIPTOR)malloc(size);
								if (pSD && GetKernelObjectSecurity(hDevice, security, pSD, size, &size))
								{
									LPTSTR sddl = nullptr;
									if (ConvertSecurityDescriptorToStringSecurityDescriptor(pSD, SDDL_REVISION_1, DACL_SECURITY_INFORMATION, &sddl, NULL))
									{
										auto path = cxStrWideToUtf8(pDetail->DevicePath);
										auto utf8SDDL = cxStrWideToUtf8(sddl);
										mapSDDLs.insert({ path, utf8SDDL });

										LocalFree(sddl);
									}
								}
								free(pSD);
							}
						}
						CloseHandle(hDevice);
					}
				}
				free(pDetail);
			}
			SetupDiDestroyDeviceInfoList(hDevInfo);

			return mapSDDLs;
		}

		/// <summary>
		/// 获取指定对象（如文件、设备）的 SACL（系统访问控制列表）字符串（SDDL格式）。
		/// 需管理员权限，并临时启用 SE_SECURITY_NAME 特权，否则无法读取 SACL。
		/// 读取完成后自动关闭特权。
		/// </summary>
		/// <param name="filePath">对象路径，如 "\\?\hid#..." 或文件路径</param>
		/// <param name="sacl">输出参数，返回 SACL 的 SDDL 字符串（如 "S:AI(AU;SA;WD;;;WD)"）</param>
		/// <returns>Win32 错误码，ERROR_SUCCESS 表示成功，其他值表示失败原因</returns>
		DWORD cxGetSACL(const char* filePath, std::string& sacl)
		{
			auto hProcess = ::GetCurrentProcess();
			if (auto enableRes = cxEnableSecurityPrivilege(hProcess, true); ERROR_SUCCESS != enableRes) {
				return enableRes;
			}

			if (HANDLE hDevice = CreateFileA(filePath, READ_CONTROL | ACCESS_SYSTEM_SECURITY,
				FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL); 
				hDevice != INVALID_HANDLE_VALUE)
			{
				PSECURITY_DESCRIPTOR pSD = nullptr;
				DWORD size = 0;
				GetKernelObjectSecurity(hDevice, SACL_SECURITY_INFORMATION, NULL, 0, &size);

				auto dwError = GetLastError();
				if (dwError == ERROR_INSUFFICIENT_BUFFER)
				{
					pSD = (PSECURITY_DESCRIPTOR)malloc(size);
					if (pSD && GetKernelObjectSecurity(hDevice, SACL_SECURITY_INFORMATION, pSD, size, &size))
					{
						LPSTR sddl = nullptr;
						if (ConvertSecurityDescriptorToStringSecurityDescriptorA(pSD, SDDL_REVISION_1, SACL_SECURITY_INFORMATION, &sddl, NULL))
						{
							sacl = sddl;
							LocalFree(sddl);
						}
					}
					free(pSD);
				}
				
				CloseHandle(hDevice);
			}

			cxEnableSecurityPrivilege(hProcess, false);

			return ::GetLastError();
		}


		/// <summary>
		/// Change HID pat's SDDL, only support admin or everyone
		/// </summary>
		/// <param name="devicePath"></param>
		/// <param name="isAdmin"></param>
		/// <param name="errMsg"></param>
		/// <returns></returns>
		bool cxSetDeviceSecurity(LPCSTR devicePath, bool isAdmin, std::string& errMsg)
		{
			HANDLE hDevice = CreateFileA(devicePath,
				WRITE_DAC | READ_CONTROL,
				FILE_SHARE_READ | FILE_SHARE_WRITE,
				nullptr,
				OPEN_EXISTING,
				0,
				nullptr);

			if (hDevice == INVALID_HANDLE_VALUE)
			{
				errMsg = std::format("Failed to open device. Error: {}", ::GetLastError());
				return false;
			}

			// 0x1201bf include following right: SDDL_READ_CONTROL | SDDL_FILE_READ | SDDL_FILE_WRITE | SDDL_FILE_EXECUTE | SDDL_KEY_READ | SDDL_KEY_WRITE | SDDL_KEY_EXECUTE
			LPCWSTR sddl = isAdmin
				? L"D:P(A;;FA;;;SY)(A;;FA;;;BA)"
				: L"D:P(A;;FA;;;SY)(A;;0x1201bf;;;BA)(A;;0x1201bf;;;WD)(A;;0x1201bf;;;RC)";

			PSECURITY_DESCRIPTOR pSD = nullptr;
			if (!ConvertStringSecurityDescriptorToSecurityDescriptorW(sddl, SDDL_REVISION_1, &pSD, nullptr))
			{
				errMsg = "Failed to convert SDDL string.";
				CloseHandle(hDevice);
				return false;
			}

			PACL pDacl = nullptr;
			BOOL bDaclPresent = FALSE;
			BOOL bDaclDefaulted = FALSE;
			if (!GetSecurityDescriptorDacl(pSD, &bDaclPresent, &pDacl, &bDaclDefaulted))
			{
				errMsg = "Failed to extract DACL from the security descriptor.";
				LocalFree(pSD);
				CloseHandle(hDevice);
				return false;
			}

			DWORD flags = isAdmin
				? DACL_SECURITY_INFORMATION
				: (DACL_SECURITY_INFORMATION | PROTECTED_DACL_SECURITY_INFORMATION);

			DWORD result = SetSecurityInfo(
				hDevice,
				SE_KERNEL_OBJECT,
				flags,
				nullptr,
				nullptr,
				pDacl,
				nullptr
			);

			LocalFree(pSD);
			CloseHandle(hDevice);

			return result == ERROR_SUCCESS;
		}
	}

	
}